package com.uusee.crawler.fetcher;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.uusee.crawler.framework.Processor;
import com.uusee.crawler.model.CrawlStatusCodes;
import com.uusee.crawler.model.CrawlURI;
import com.uusee.httpclient.SingleHttpConnectionManager;

public class FetchImage extends Processor {
	private static Log log = LogFactory.getLog("FetchHTTP");
	
	public static final String RANGE = "Range";
	public static final String RANGE_PREFIX = "bytes=0-";
	private static Integer DEFAULT_SOTIMEOUT_MS = new Integer(20000);
	
	protected void innerProcess(CrawlURI crawlUri){
		HttpMethod method = null;
		InputStream in = null;
		try {
			String crawlUrl = crawlUri.getCrawlUrl();
			String charset = crawlUri.getCharset();

			//HttpConnectionManager cm = new ThreadLocalHttpConnectionManager();
			HttpConnectionManager cm = new SingleHttpConnectionManager();

			// TODO: The following settings should be made in the corresponding
			// HttpConnectionManager, not here.
			HttpConnectionManagerParams hcmp = cm.getParams();
			hcmp.setConnectionTimeout(DEFAULT_SOTIMEOUT_MS);
			//hcmp.setStaleCheckingEnabled(true);
			// Minimizes bandwidth usage. Setting to true disables Nagle's
			// algorithm. IBM JVMs < 142 give an NPE setting this boolean
			// on ssl sockets.
			hcmp.setTcpNoDelay(false);

			HttpClient http = new HttpClient(cm);
			HttpClientParams hcp = http.getParams();
			// Set default socket timeout.
			hcp.setSoTimeout(DEFAULT_SOTIMEOUT_MS);
			// Set client to be version 1.0.
			hcp.setVersion(HttpVersion.HTTP_1_0);

			// configureHttpCookies();

			// Configure how we want the method to act.
			http.getParams().setParameter(HttpMethodParams.SINGLE_COOKIE_HEADER, new Boolean(true));
			http.getParams().setParameter(HttpMethodParams.UNAMBIGUOUS_STATUS_LINE, new Boolean(false));
			http.getParams().setParameter(HttpMethodParams.STRICT_TRANSFER_ENCODING, new Boolean(false));
			http.getParams().setIntParameter(HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT, 10);

			method = new GetMethod(crawlUrl);
			configureMethod(method, charset);

			int statusCode = http.executeMethod(method);
			
			if (statusCode == HttpStatus.SC_OK) {
				crawlUri.setCrawlBytes(method.getResponseBody());
				crawlUri.setCrawlStatus(CrawlStatusCodes.FETCH_SUCCESS);
			} else {
				log.info(crawlUri.getCrawlUrl()+"----Fetch Failure.StatusCode="+statusCode);
				crawlUri.setCrawlStatus(CrawlStatusCodes.FETCH_SC_NOT_OK);
			}
		} catch (IOException e) {
			log.error(crawlUri.getCrawlUrl()+"----Fetch Error.",e);
			crawlUri.setCrawlStatus(CrawlStatusCodes.FETCH_EXCEPTION);
		} catch (Exception e) {
			log.error(crawlUri.getCrawlUrl()+"----Fetch Error.",e);
			crawlUri.setCrawlStatus(CrawlStatusCodes.FETCH_EXCEPTION);
		} finally {
			if (method != null) {
				method.releaseConnection();
			}
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					
				}
				
			}
		}
	}
	
	private static void configureMethod(HttpMethod method, String encoder) {
		// Don't auto-follow redirects
		method.setFollowRedirects(false);

		// Use only HTTP/1.0 (to avoid receiving chunked responses)
		method.getParams().setVersion(HttpVersion.HTTP_1_0);

		method.setRequestHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;)");
		method.setRequestHeader("From", "abc@gmail.com");
		method.addRequestHeader("Content-type", "text/html; charset=" +encoder);

		// Set retry handler.
		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new CrawlerHttpMethodRetryHandler());

		// final long maxLength = getMaxLength(curi);
		// if(maxLength > 0) {
		// method.addRequestHeader(RANGE,
		// RANGE_PREFIX.concat(Long.toString(maxLength - 1)));
		// }

		//HostConfiguration config = new HostConfiguration(http.getHostConfiguration());
		// configureProxy(curi, config);
		// configureBindAddress(curi, config);
		//return config;
	}
}
